

function Application(){

	// Global attributes
	
	var globalThis = this;
	
	this.example = [];
	
	// Attributes
	
	this.fileHandler = null;
	
	this.actionManager = null;
	
	this.action = null;
	
	this.shapeManager = null;
	
	this.canvasManager = null;
	
	this.timeRecorder = null;
	
	this.interfaces = null;
	
	this.drawing = false;
	
	this.selecting = false;
	
	this.moving = false;
	
	this.resizing = false;
	
	this.rotating = false;
	
	this.isAdded = false;
	
	this.currentWorkingShape = null;
	
	this.currentHoverShape = null;
	
	this.mouseCoords = {x:null, y:null};
	
	this.previousMouseCoords = {x:null, y:null};
	
	this.pressedCoordinates = {x:null, y:null};
	
	// Static attributes
	
	Application.draw = true;
	
	Application.select = false;
	
	Application.mSelect = false;
	
	Application.externalEvent = null; // Can contain data
	
	Application.eraserEvent = false;
	
	// Static methodes
	
	Application.setFunction = function(drawState, selectState, mSelectState, externalEvent, eraserEvent){
		Application.draw = drawState;
		Application.select = selectState;
		Application.mSelect = mSelectState;
		Application.externalEvent = externalEvent;
		Application.eraserEvent = eraserEvent;
	}
	
	
	// Setter & Getters
	
	this.getFileHandler = function(){
		return this.fileHandler;
	}
	
	this.setFileHandler = function(fileHandler){
		this.fileHandler = fileHandler;
	}
	
	this.isResizing = function(){
		return this.resizing;
	}
	
	this.setResizing = function(state){
		this.resizing = state;
	}
	
	this.isMoving = function(){
		return this.moving;
	}
	
	this.setMoving = function(state){
		this.moving = state;
	}
	
	this.isRotating = function(){
		return this.rotating;
	}
	
	this.setRotating = function(state){
		this.rotating = state;
	}
	
	this.isDrawing = function(){
		return this.drawing;
	}
	
	this.setDrawing = function(state){
		this.drawing = state;
	}
	
	this.isSelecting = function(){
		return this.selecting;
	}
	
	this.setSelecting = function(state){
		this.selecting = state;
	}
	
	this.setCurrentWorkingShape = function (index){
		this.currentWorkingShape = index;
	}
	
	this.getCurrentWorkingShape = function (){
		return this.currentWorkingShape;
	}
	
	this.setCurrentHoverShape = function (index){
		this.currentHoverShape = index;
	}
	
	this.getCurrentHoverShape = function (){
		return this.currentHoverShape;
	}
	
	this.setActionManager = function(actionManager){
		this.actionManager = actionManager;
	}
	
	this.getActionManager = function(){
		return this.actionManager;
	}
	
	this.setShapeManager = function(shapeManager){
		this.shapeManager = shapeManager;
	}
	
	this.setCanvasManager = function(canvasManager){
		this.canvasManager = canvasManager;
	}
	
	this.setTimeRecorder = function(timeRecorder){
		this.timeRecorder = timeRecorder;
	}
	
	this.setInterfaces = function(interfaces){
		this.interfaces = interfaces;
	}
	
	this.getInterfaces = function(interfaces){
		return this.interfaces;
	}
	
	this.getShapeManager = function(shapeManager){
		return this.shapeManager;
	}
	
	this.getCanvasManager = function(canvasManager){
		return this.canvasManager;
	}
	
	this.getTimeRecorder = function(timeRecorder){
		return this.timeRecorder;
	}
	
	// Searching operations (which is a cake)
	
	this.getShapeId = function(x,y){
	
		var data = this.getShapeManager().getData();
		
		// Looping through all the shapes created
		for (var i = 0 ; i < data.length ; i++){
			
			var curShape = data[i];
			
			// Checking if we are in the 'box' of the shape
			// If we are loop through the points
			// If not, skip to next shape
			
			if (curShape.isPointInCanvas(x,y)){
				// Now we know that we are in the 'box'
				// We gonna check each point individually
				
				if (curShape.isMouseOverPath(x,y)){
					return i;
				}
			}
		}
		
		// Haven't found any shape return null
		return null;
	}
	
	// Eraser action
	
	this.appStartEraser = function(event){
		
			
	}
	
	this.appMoveEraser = function(event){
		var tmp = this.getShapeId(event.x, event.y)
		
		console.log(tmp);
	}
	
	this.appEndEraser = function(event){
	}
	
	// Drawing actions
	
	this.appStartDraw = function(event){
		
		// Keep drawing until appEndDraw is called
		this.setDrawing(true);
		
		this.getShapeManager().addShape(this.getInterfaces().getShape(),
										this.getInterfaces().getTool().getColor(),
										this.getInterfaces().getTool().getThickness());
		
		// Initialising the shape
		this.getShapeManager().getLastShape().initShape(this.mouseCoords.x, this.mouseCoords.y);
		
		// Enabling the timer
		this.timeRecorder.start();	
	}
	
	this.appMoveDraw = function(event){
		
		if (this.isDrawing()){
			
			// Filling the buffers of the shape
			this.getShapeManager().getLastShape().fillShape(this.mouseCoords.x, this.mouseCoords.y, this.timeRecorder.get_ticks());
			//console.log(this.mouseCoords.x + "    "  + this.mouseCoords.y);
			
			// Updating canvas state
			this.getCanvasManager().drawShape(this.getShapeManager().getData()[this.getShapeManager().lastIndex()],
											  this.getCanvasManager().getFrontCanvas(),
											  true);
		}
	}
	
	this.appEndDraw = function(event){
		
		// Stops the drawing
		this.setDrawing(false);
		
		// Disabling the timer
		this.timeRecorder.start();
		
		// Adding to cache
		this.getShapeManager().getLastShape().endShape();
		
		// Clearing the front canvas
		this.getCanvasManager().clearCanvas(0,
											0, 
											this.getCanvasManager().getFrontCanvas().getCanvas().width,
											this.getCanvasManager().getFrontCanvas().getCanvas().height,
											this.getCanvasManager().getFrontCanvas());
											
		// Drawing the last shape on the back canvas
		this.getCanvasManager().drawOptimisedShape(this.getShapeManager().getData()[this.getShapeManager().lastIndex()],
												   this.getCanvasManager().getBackCanvas());
	}
	
	// Selecting action (rotate, resize included)
	this.appStartSelect = function(event){
		
		var tmpShape = null;
		var tmpShape2 = null;
		
		
		this.setSelecting(true);
		
		// We already have something selected
		if (this.getCurrentWorkingShape() != null){
			
			//tmpShape = this.getShapeId(this.mouseCoords.x, this.mouseCoords.y);
			
			tmpShape = this.getShapeManager().getData()[this.getCurrentWorkingShape()];
			
			// We clicked on the 'selecting' box
			if (tmpShape.isPointInCanvas(this.mouseCoords.x, this.mouseCoords.y)){
			
				tmpShape2 = this.getShapeId(this.mouseCoords.x, this.mouseCoords.y);
				// Checking that nothing is inside
				if (tmpShape2 != null && tmpShape2 != this.getCurrentWorkingShape()){
					this.setCurrentWorkingShape(this.getShapeId(this.mouseCoords.x, this.mouseCoords.y));
				}
				else{
					// Detect if we pressed on the resize points, rotate points ...
					
					if (tmpShape.getResizePoints(this.mouseCoords.x, this.mouseCoords.y) != null){
						// Setting the resize point, used for cursor style later
						this.setResizing(true);
						tmpShape.setResizePoint(tmpShape.getResizePoints());
							
						
					}
					else if (tmpShape.getRotatePoints(this.mouseCoords.x, this.mouseCoords.y) != null){
						// Setting the rotate point, used for cursor style later
						this.setRotating(true);
						tmpShape.setResizePoint(tmpShape.getResizePoints());
					}
					else{
						// Moving the shape
						if (!this.isAdded){
							this.action = new Action(MOVE_ACTION);
							this.action.recordInitialState(this.getCurrentWorkingShape(),
														   this.getShapeManager().getData()[this.getCurrentWorkingShape()]);
							this.isAdded = true;
						}
						this.setMoving(true);
					}
				}
				
			}
			else{
				this.setCurrentWorkingShape(this.getShapeId(this.mouseCoords.x, this.mouseCoords.y));
			}
		}
		else{
			this.setCurrentWorkingShape(this.getShapeId(this.mouseCoords.x, this.mouseCoords.y));
		}
	}
	
	this.appMoveSelect = function(event){
		
		//console.log("TESTING : " +  this.getCurrentWorkingShape());
		
		var tmpShape = this.getShapeId(this.mouseCoords.x, this.mouseCoords.y);
		
		if (!this.isSelecting()){
		
			// We already have something selected
			if (this.getCurrentWorkingShape() != null){
				var curShape = this.getShapeManager().getData()[this.getCurrentWorkingShape()];
				
				if (curShape.isPointInCanvas(this.mouseCoords.x, this.mouseCoords.y) || tmpShape != null){
					if (tmpShape != null){
					//console.log(tmpShape);
					}
					this.getCanvasManager().setCursorStyle("all-scroll");
				}
				else{
					this.getCanvasManager().setCursorStyle("default");
				}
			}
			else{
				if (tmpShape != null){
					//console.log("HERE " + tmpShape);
					this.getCanvasManager().setCursorStyle("all-scroll");
				}
				else{
					this.getCanvasManager().setCursorStyle("default");
				}
			}
		}
		else{
			if (this.getCurrentWorkingShape() != null){
				var curShape = this.getShapeManager().getData()[this.getCurrentWorkingShape()];
				if (this.isMoving()){
					curShape.move(this.previousMouseCoords.x - this.mouseCoords.x,
								  this.previousMouseCoords.y - this.mouseCoords.y);
				}
				else if (this.isResizing()){
					//this.getCurrentWorkingShape().resize(this.mouseCoords.x, this.mouseCoords.y);
				}
				else{
					//this.getCurrentWorkingShape().rotate(this.mouseCoords.x, this.mouseCoords.y);
				}
			}
		}
		
		// Knowing that everything is drawn on the back canvas
		// We can safely clear the front one
		// It won't affect the performance since we only have to redraw the box and the shape
		this.getCanvasManager().clearCanvas(0,
											0,
											this.getCanvasManager().getFrontCanvas().getCanvas().width,
											this.getCanvasManager().getFrontCanvas().getCanvas().height,
											this.getCanvasManager().getFrontCanvas());
												
		// We're gonna redraw everything using the cache canvas
		// So it will almost not affect the performance at all
		this.getCanvasManager().clearCanvas(0,
											0,
											this.getCanvasManager().getBackCanvas().getCanvas().width,
											this.getCanvasManager().getBackCanvas().getCanvas().height,
											this.getCanvasManager().getBackCanvas());
											
		
											
		if (this.getCurrentWorkingShape() != null){
			
			
				
			// Redraw the back canvas using the cache canvas of each shape
			// Except the one we are currently working on
			this.getCanvasManager().drawOptimisedCanvas(this.getShapeManager().getData(),
														this.getCanvasManager().getBackCanvas(),
														this.getCurrentWorkingShape());
											
			// Drawing the working shape on the front canvas
			this.getCanvasManager().drawOptimisedShape(this.getShapeManager().getData()[this.getCurrentWorkingShape()],
													   this.getCanvasManager().getFrontCanvas());
			
			this.getShapeManager().getData()[this.getCurrentWorkingShape()].drawBox(
																			this.getCanvasManager().
																			getFrontCanvas());
		}
		else{
			this.getCanvasManager().drawOptimisedCanvas(this.getShapeManager().getData(),
														this.getCanvasManager().getBackCanvas(),
														null);
		}
	}
	
	this.appEndSelect = function(event){
	
		this.setSelecting(false);
		this.setRotating(false);
		this.setResizing(false);
		this.setMoving(false);
		this.isAdded = false;
	}
	
	
	this.appStartMultipleSelect = function(event){
		
		this.setSelecting(true);

		this.getCanvasManager().clearCanvas(0,
												0,
												this.getCanvasManager().getFrontCanvas().getCanvas().width,
												this.getCanvasManager().getFrontCanvas().getCanvas().height,
												this.getCanvasManager().getFrontCanvas());
		
		this.pressedCoordinates.x = this.mouseCoords.x;
		this.pressedCoordinates.y = this.mouseCoords.y;
	}
	
	this.appMoveMultipleSelect = function(event){
		
		if (this.isSelecting()){
			
			this.getCanvasManager().clearCanvas(0,
												0,
												this.getCanvasManager().getFrontCanvas().getCanvas().width,
												this.getCanvasManager().getFrontCanvas().getCanvas().height,
												this.getCanvasManager().getFrontCanvas());
			
			this.getCanvasManager().getFrontCanvas().getContext().beginPath();
			this.getCanvasManager().getFrontCanvas().getContext().strokeStyle="rgba(0, 0, 255, 1)";
			this.getCanvasManager().getFrontCanvas().getContext().lineWidth="1"; 
			
			this.getCanvasManager().getFrontCanvas().getContext().rect(this.pressedCoordinates.x,
																	   this.pressedCoordinates.y,
																	   this.mouseCoords.x - this.pressedCoordinates.x,
																	   this.mouseCoords.y - this.pressedCoordinates.y);
			
			
			
			this.getCanvasManager().getFrontCanvas().getContext().stroke();
		}
	}
	
	this.appEndMultipleSelect = function(event){
	
		this.setSelecting(false);
		
		var data = this.getShapeManager().getData();
		
		// Looping through all the shapes created
		for (var i = 0 ; i < data.length ; i++){
			
			var curShape = data[i];
			
			if (curShape.isShapeInSelectedBox(this.pressedCoordinates.x,
																 this.pressedCoordinates.y,
																 this.mouseCoords.x,
																 this.mouseCoords.y)){
																 
				
				// Adding it in the array
				
				this.example.push(i);
			}
			
			
																 
			
		}
		
		for (var i = 0 ; i < this.example.length ; i++){
			data[this.example[i]].drawBox(this.getCanvasManager().
																			getFrontCanvas());	
		}
		
		this.pressedCoordinates.x = null;
		this.pressedCoordinates.y = null;		
	}
	
	// Actions
	
	function getPosition(e) {

		var targ;
		if (!e)
			e = window.event;
		if (e.target)
			targ = e.target;
		else if (e.srcElement)
			targ = e.srcElement;
		if (targ.nodeType == 3) // safari
			targ = targ.parentNode;

		// jQuery normalizes the pageX and pageY
		// pageX,Y are the mouse positions relative to the document
		// offset() returns the position of the element relative to the document
		
		var x = e.pageX - $(targ).offset().left;
		var y = e.pageY - $(targ).offset().top;
		
		//var x = e.touches[0].pageX;
		//var y = e.touches[0].pageY;

		return {"x": x, "y": y};
};

	
	this.appStartAction = function(event){
		
		this.example = [];
		
		event.preventDefault();
		
		//this.mouseCoords.x = event.offsetX;
		//this.mouseCoords.y = event.offsetY;
		
		this.mouseCoords = getPosition(event);
		
		if (Application.draw){
			this.action = new Action(DRAW_ACTION);
			this.action.recordInitialState(null);
			this.appStartDraw(event);
		}
		else if (Application.select){
			this.appStartSelect(event);
		}
		else if (Application.mSelect){
			this.appStartMultipleSelect(event);
		}
		else if (Application.eraserEvent){
			this.appStartEraser(event);
		}
		else{
			this.getShapeManager().getData().push(this.getFileHandler().importedShapes[Application.externalEvent]);
			this.getCanvasManager().drawOptimisedCanvas(this.getShapeManager().getData(),
														this.getCanvasManager().getBackCanvas(),
														null);
			}
	}
	
	this.appMoveAction = function(event){
		
		event.preventDefault();
		
		
		this.previousMouseCoords.x = this.mouseCoords.x;
		this.previousMouseCoords.y = this.mouseCoords.y;
		
		//this.mouseCoords.x = event.offsetX;
		//this.mouseCoords.y = event.offsetY;
		
		this.mouseCoords = getPosition(event);
		
		
		if (Application.draw){
			this.action = new Action(DRAW_ACTION);
			this.action.recordInitialState(null);
			this.appMoveDraw(event);
		}
		else if (Application.select){
			this.appMoveSelect(event);
		}
		else if (Application.eraserEvent){
			this.appMoveEraser(event);
		}
		else{
			this.appMoveMultipleSelect(event);
		}
	}
	
	this.appEndAction = function(event){
		
		if (Application.draw){
			this.action = new Action(DRAW_ACTION);
			this.action.recordInitialState(null);
			this.appEndDraw(event);
		}
		else if (Application.select){
			this.appEndSelect(event);
		}
		else if (Application.eraserEvent){
			this.appEndEraser(event);
		}
		else{
			this.appEndMultipleSelect(event);
		}
		
		
		
		if (this.action != null){
			this.action.recordFinalState(this.getShapeManager().getData()[this.getCurrentWorkingShape()]);
			
			
			this.getActionManager().flushDataBackup();
			this.getActionManager().addAction(this.action);
			this.action = null;
		}
	}
	
	this.createWindow = function(){
	
		$('canvas').attr('width',( (67/100) * $(window).width()));
		$('#canvases').width(( (67/100) * $(window).width()));
		
		$('canvas').attr('height',$(window).height());
		$('#canvases').height($(window).height());
		
		
		
		
		for (i=2; i<=14; i+=2){
			if(i==2)
			$('#thickness').append("<option value="+i+" selected=\"selected\"> " + i + "</option>");
			else
			$('#thickness').append("<option value="+i+"> " + i + "</option>");
		}
		
		//if (simple_window){
			$('#menu').width(( (30/100) * $(window).width()));
			$('#menu').height($(window).height());
			
			
			$('#layerButton').width(( (90/100) * $(menu).width()));
			
			$('#shapeNumber').replaceWith("Shape number : " + this.getCanvasManager().getRedrawer().index);
			
			$('#colorPicker').attr('value', this.getInterfaces().getColor().toHex());
			
			$('#layerButton').hide();
			
			$('#layerButton').show();
			
			$('#rangeThickness').attr('value', this.getInterfaces().getThickness());
			
			
			/*$('#scrollbutton').width( (6/100) * $('#menu').width());
			$('#scrollbutton').height($(window).height());
			$('#scrollbutton').css({
				"display" : "inline-block",
				"vertical-align" : "top"
			});*/
			
			/*$('#allControls').width( (90/100) * $('#menu').width());
			$('#allControls').height($(window).height());
			$('#allControls').css({
				"display" : "inline-block"
			});*/
			
			
			
			
			
			/*if (current_id != null){
				
				$('#shape_number').text("Shape number : " + current_id);
				$('#shape_thickness').text("Shape thickness : " + shape_manager.data[current_id].thickness);
				$('#shape_color').text("Shape number : " + shape_manager.data[current_id].color.toString());
				$('#shape_number').show();
				$('#shape_thickness').show();
				$('#shape_color').show();
			}
			else
			{
				$('#shape_number').hide();
				$('#shape_thickness').hide();
				$('#shape_color').hide();
			}*/
	//	}
		/*else{
			$('#menu').width(( (51/100) * $(window).width()));
			$('#menu').height($(window).height());

			
			$('#scrollbuttoninput').width( (6/100) * $('#menu').width());
			$('#scrollbuttoninput').height($(window).height());
			
			$('#scrollbutton').width( (6/100) * $('#menu').width());
			$('#scrollbutton').height($(window).height());
			$('#scrollbutton').css({
				"display" : "inline-block",
				"vertical-align" : "top"
			});
			
			$('#allControls').width( (90/100) * $('#menu').width());
			$('#allControls').height($(window).height());
			$('#allControls').css({
				"display" : "inline-block"
			});
			$('#scrollbuttoninput').prop("value",">>");
			
			$('#menu').css({
				"position" : "absolute",
			});
			
			
		}*/
	}
	
	
	// Ugly function, needs to be recoded
	this.loadFile = function(){
	
		var loadedData;
		var files = document.getElementById('files').files;
		if (!files.length) {
		  alert('Please select a file!');
		  return;
		}

		var file = files[0];
		var start = 0;
		var stop = file.size - 1;

		var reader = new FileReader();
		
		var blob = file.slice(start, stop + 1);
		
		reader.readAsArrayBuffer(blob);
		
		
		//this.data = [];
		
		reader.onloadend = function(evt) {

		  if (reader.readyState == FileReader.DONE) 
		  {
			
			globalThis.setShapeManager(new ShapeManager());
			
			globalThis.setCanvasManager(new CanvasManager());
			
			// Unziping
			
			 unzipBlob(blob, function(unzippedBlob) {
				
				//console.log(blob);
				
				//console.log(unzippedBlob);
				
				// read it as arraybuffer
				
				reader.readAsArrayBuffer(unzippedBlob);
				
				reader.onloadend = function(evt) {
					
					 if (reader.readyState == FileReader.DONE) {
						loadedData = new DataView(evt.target.result);
						
						var byteoffset = 0;
					
						var dataLength = loadedData.getUint16(byteoffset);	byteoffset+=2;

						for (var i = 0 ; i < dataLength ; i++)
						{
							/*var type = loadedData.getUint8(byteoffset);	byteoffset++;
							
							if (type == 0)
								globalThis.getShapeManager().addShape("Free",
																  globalThis.getInterfaces().getTool().getColor(),
																  globalThis.getInterfaces().getTool().getThickness());
							else if (type == 1)
								globalThis.getShapeManager().addShape("Circle",
																  globalThis.getInterfaces().getTool().getColor(),
																  globalThis.getInterfaces().getTool().getThickness());*/
							
							
							console.log((i+1) + " / " + dataLength + " shapes created !");  
							
							
							globalThis.getShapeManager().addShape(globalThis.getInterfaces().getShape(),
																  globalThis.getInterfaces().getTool().getColor(),
																  globalThis.getInterfaces().getTool().getThickness());
							

										
							byteoffset = globalThis.getShapeManager().getData()[i].loadFromFile(loadedData, byteoffset);
											
						}
						
						 // Draw everything
		  
		  globalThis.getCanvasManager().drawOptimisedCanvas(globalThis.getShapeManager().getData(),
														    globalThis.getCanvasManager().getBackCanvas(),
														    null);
															
		  globalThis.setActionManager(new ActionManager(globalThis.getShapeManager(), globalThis.getCanvasManager()));
					}
				}
				
			  });
		  }
		  
		 
		  
		}; // End of onload
		
		console.log("Here : ----------------------------------------------");
		for (var i = 0 ; i < this.getShapeManager().getData().length ; i++){
		//console.log(this.getShapeManager().getData()[i].color.toString());
		}
		
		function zipBlob(filename, blob, callback) {
		  // use a zip.BlobWriter object to write zipped data into a Blob object
		  zip.createWriter(new zip.BlobWriter("application/zip"), function(zipWriter) {
			// use a BlobReader object to read the data stored into blob variable
			zipWriter.add(filename, new zip.BlobReader(blob), function() {
			  // close the writer and calls callback function
			  zipWriter.close(callback);
			});
		  }, onerror);
		}

		function unzipBlob(blob, callback) {
		  // use a zip.BlobReader object to read zipped data stored into blob variable
		  zip.createReader(new zip.BlobReader(blob), function(zipReader) {
			// get entries from the zip file
			zipReader.getEntries(function(entries) {
			  // get data from the first file
			  entries[0].getData(new zip.BlobWriter("text/plain"), function(data) {
				// close the reader and calls callback function with uncompressed data as parameter
				zipReader.close();
				callback(data);
			  });
			});
		  }, onerror);
		}

		function onerror(message) {
		  console.error(message);
		}
		
	} // End of file load
	
	/*this.loadFile = function(){
	
		var loadedData;
		var files = document.getElementById('files').files;
		if (!files.length) {
		  alert('Please select a file!');
		  return;
		}

		var file = files[0];
		var start = 0;
		var stop = file.size - 1;

		var reader = new FileReader();
		
		var blob = file.slice(start, stop + 1);
		reader.readAsArrayBuffer(blob);
		this.data = [];
		
		reader.onloadend = function(evt) {

		  if (evt.target.readyState == FileReader.DONE) 
		  {
			globalThis.setShapeManager(new ShapeManager());
			
			globalThis.setCanvasManager(new CanvasManager());

			loadedData = new DataView(evt.target.result);
			
			var byteoffset = 0;
			
			var dataLength = loadedData.getUint16(byteoffset);	byteoffset+=2;

			for (var i = 0 ; i < dataLength ; i++)
			{
				/*var type = loadedData.getUint8(byteoffset);	byteoffset++;
				
				if (type == 0)
					shape_manager.addShape(new Shape(0, 0));
				else if (type == 1)
					shape_manager.addShape(new Circle(0, 0));
				
				
				console.log((i+1) + " / " + dataLength + " shapes created !");  
				
				
				globalThis.getShapeManager().addShape(globalThis.getInterfaces().getShape(),
													  globalThis.getInterfaces().getTool().getColor(),
													  globalThis.getInterfaces().getTool().getThickness());
				

							
				byteoffset = globalThis.getShapeManager().getData()[i].loadFromFile(loadedData, byteoffset);	
								
			}
		  }
		  
		  // Draw everything
		  
		  globalThis.getCanvasManager().drawOptimisedCanvas(globalThis.getShapeManager().getData(),
														    globalThis.getCanvasManager().getBackCanvas(),
														    null);
															
		  globalThis.setActionManager(new ActionManager(globalThis.getShapeManager(), globalThis.getCanvasManager()));
		};
		
		console.log("Here : ----------------------------------------------");
		for (var i = 0 ; i < this.getShapeManager().getData().length ; i++){
		//console.log(this.getShapeManager().getData()[i].color.toString());
		}
	}*/
	
	this.saveFile = function(){
		// Setting up the beginnig of the file
		
		console.log("Start blob creation");
	
		var size = 0;
		
		var byteoffset = 0;
		
		size += 2; // Number of shapes, 2 bytes is enough ! (data.length)
		
		for (var i = 0 ; i < this.getShapeManager().getData().length ; i++)
		{
			size = size + this.getShapeManager().getData()[i].getBinarySize();
		}
		
		var buffer = new ArrayBuffer(size); 
		
		var data = new DataView(buffer);
		
		
		data.setUint16(byteoffset, this.getShapeManager().getData().length);	byteoffset+=2;
		
		for (var i = 0 ; i < this.getShapeManager().getData().length ; i++)
		{
			byteoffset = this.getShapeManager().getData()[i].generateHexString(data, byteoffset);
		}
		
		console.log("Final Byteoffset = " + byteoffset + " max -> " + size);
		
		
		
		var bb = new Blob([data], {type: 'application/octet-binary'});
		
		console.log("End blob creation");
		
		
		//var blob = bb.getBlob("example/binary");
		
		zipBlob(document.getElementById("saveFileName").value, bb, function(zippedBlob) {
			saveAs(zippedBlob, document.getElementById("saveFileName").value);
		});
		
		//saveAs(bb, document.getElementById("saveFileName").value);
		
		function zipBlob(filename, blob, callback) {
		  // use a zip.BlobWriter object to write zipped data into a Blob object
		  zip.createWriter(new zip.BlobWriter("application/zip"), function(zipWriter) {
			// use a BlobReader object to read the data stored into blob variable
			zipWriter.add(filename, new zip.BlobReader(blob), function() {
			  // close the writer and calls callback function
			  zipWriter.close(callback);
			});
		  }, onerror);
		}

		function unzipBlob(blob, callback) {
		  // use a zip.BlobReader object to read zipped data stored into blob variable
		  zip.createReader(new zip.BlobReader(blob), function(zipReader) {
			// get entries from the zip file
			zipReader.getEntries(function(entries) {
			  // get data from the first file
			  entries[0].getData(new zip.BlobWriter("text/plain"), function(data) {
				// close the reader and calls callback function with uncompressed data as parameter
				zipReader.close();
				callback(data);
			  });
			});
		  }, onerror);
		}

		function onerror(message) {
		  console.error(message);
		}
	} // End of file saving
	
	
	
	
	//========================================
	// Constructor
	//========================================
	
	this.setFileHandler(new FileHandler());
	
	this.setShapeManager(new ShapeManager());
	
	this.setCanvasManager(new CanvasManager());
	
	this.setActionManager(new ActionManager(this.getShapeManager(), this.getCanvasManager()));
	
	this.setTimeRecorder(new Timer());
	
	this.setInterfaces(new Interface());

	// Adding canvas events
	
	this.getCanvasManager().getFrontCanvas().getCanvas().
											addEventListener('mousedown', function(event){
																				globalThis.appStartAction(event);
																		  }, false);
	this.getCanvasManager().getFrontCanvas().getCanvas().
											addEventListener('mousemove', function(event){
																				globalThis.appMoveAction(event);
																		  }, false);																	  
	this.getCanvasManager().getFrontCanvas().getCanvas().
											addEventListener('mouseup', function(event){
																				globalThis.appEndAction(event);
																		  }, false);
																		  
	this.getCanvasManager().getFrontCanvas().getCanvas().
											addEventListener('touchstart', function(event){
																				globalThis.appStartAction(event);
																		  }, false);
	this.getCanvasManager().getFrontCanvas().getCanvas().
											addEventListener('touchmove', function(event){
																				globalThis.appMoveAction(event);
																		  }, false);																	  
	this.getCanvasManager().getFrontCanvas().getCanvas().
											addEventListener('touchend', function(event){
																				globalThis.appEndAction(event);
																		  }, false);
																		  
	$('#version').append(APP_VERSION);
	
	
	// Creating window
	this.createWindow();
	
	
	// Adding window event listener
	
	$( window ).resize(function() {
		globalThis.createWindow();
		globalThis.getCanvasManager().drawOptimisedCanvas(globalThis.getShapeManager().getData(),
														  globalThis.getCanvasManager().getBackCanvas());
	});
	
	
}